#include "AdministradorMemoriaCompartida.h"
extern map<key_t, SharedMemory*> mapaMemorias;
extern map<key_t, Semaforo*> semaforosMemorias;
extern int cantidad;

//************************************************************
// constructor que recibe como parámetro un puntero al torneo
AdministradorMemoriaCompartida::AdministradorMemoriaCompartida() {
	cantidad = 0;
}

//************************************************************
// destructor
AdministradorMemoriaCompartida::~AdministradorMemoriaCompartida() {
}

//************************************************************
// a una determinada partida, le asigno una shared memory de lec y escr para comunicarse con el servidor del torneo
void AdministradorMemoriaCompartida::asignarShm(key_t key, bool liberar) {
	// seteo una shared mem para escritura
	SharedMemory* memoriaPartida = new SharedMemory(key);
	ostringstream ss;
	ss << "sem" << key;
	Semaforo* semaforo = new Semaforo(0, ss.str().c_str());
	if (!memoriaPartida->conectarShm()) {
		perror(" [ERROR] Error al conectar a la Shared Memory");
		exit(1);
	}
	mapaMemorias[key] = memoriaPartida;
	semaforosMemorias[key] = semaforo;
	cantidad++;
	if (liberar) {
		semaforo->V();
	}
}

/////////////////////////////////////////////// Lee los datos desde la SHM en base al idPartida
t_partida AdministradorMemoriaCompartida::leerDatos(int idPartida) {
	semaforosMemorias[idPartida]->P();
	t_partida partida = mapaMemorias[idPartida]->leerDatos();
	semaforosMemorias[idPartida]->V();
	return partida;
}

//************************************************************
// Escribe los datos en la SHM en base al idPartida
bool AdministradorMemoriaCompartida::escribirDatos(t_partida* partida, int idPartida) {
	semaforosMemorias[idPartida]->P();
	bool respuesta = mapaMemorias[idPartida]->escribirDatos(partida);
	semaforosMemorias[idPartida]->V();
	return respuesta;
}

//************************************************************
// cierra una shared memory para el idPartida pasado por parámetro

void AdministradorMemoriaCompartida::cerrarShm(int idPartida) {
	mapaMemorias[idPartida]->conectarShm();
	mapaMemorias[idPartida]->cerrarShm();
	free(mapaMemorias[idPartida]);
	mapaMemorias[idPartida]=NULL;
}


//************************************************************
// a una determinada partida, le asigno una shared memory de lec y escr para comunicarse con el servidor del torneo
void AdministradorMemoriaCompartida::conectarShm(key_t key) {
	// seteo una shared mem para escritura
	ostringstream ss;
	ss << "sem" << key;

	/* Libero la memoria si ya existian */
	free(mapaMemorias[key]);
	free(semaforosMemorias[key]);

	/* Las vuelvo a instanciar */
	mapaMemorias[key] = new SharedMemory(key);
	mapaMemorias[key]->conectarShm();
	semaforosMemorias[key] = new Semaforo(1, ss.str().c_str());
}

void AdministradorMemoriaCompartida::eliminarSemaforo(int idPartida) {
	semaforosMemorias[idPartida]->Liberar();
	semaforosMemorias[idPartida]->Eliminar();
	free(semaforosMemorias[idPartida]);
	semaforosMemorias[idPartida] = NULL;
}

int AdministradorMemoriaCompartida::getCantidad() {
	return (cantidad);
}

void AdministradorMemoriaCompartida::liberarTodo() {
	for (map<key_t, SharedMemory*>::iterator it = mapaMemorias.begin(); it != mapaMemorias.end(); ++it) {
		if(mapaMemorias[it->first] != NULL)
			this->cerrarShm(it->first);
		if(semaforosMemorias[it->first] != NULL)
			this->eliminarSemaforo(it->first);
	}
}
